package ivan.bookKeeper;

import java.sql.Date;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;

import so.book.AddBook;
import so.book.ReturnBooks;
import so.book.UpdateBook;
import so.bookFromLibrary.AddBookFromLibrary;
import so.bookFromLibrary.ReturnBooksFromLibrary;
import so.library.ReturnAllLibraries;
import util.DialogCreator;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.DialogInterface;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ArrayAdapter;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import domain.Book;
import domain.BookFromLibrary;
import domain.Library;

public class AddBookActivity extends Activity implements OnClickListener {
	private static final String TAG = AddBookActivity.class.getSimpleName();
	private static final int DIALOG_ENTER_NAME = 1;
	private static final int DIALOG_ENTER_AUTHOR = 2;
	private static final int DIALOG_ENTER_PUBLISHER = 3;
	private static final int DIALOG_ENTER_LANGUAGE = 4;
	private static final int DIALOG_ENTER_ISBN = 5;
	private static final int DIALOG_ENTER_YEAR = 6;
	private static final int DIALOG_SHOW_SPINNER = 7;
	private TextView txtBookName;
	private TextView txtBookAuthor;
	private ExpandableListView expListAdditionalOptions;
	private BaseExpandableListAdapter expListAdapter;
	private boolean isEdit = false;

	private Map<String, Object> map;
	private static TextView[] additionalListTextViews = new TextView[4];

	private Book book;
	private Library library;
	private ImageButton buttonAddBook;

	private static DialogCreator dialogCreator = null;

	private ImageButton buttonAddLibraryForThisBook;
	private ArrayAdapter<Library> libraryAdapter;
	private Library selectedLibrary = null;

	// private int day, month, year;
	// private final Calendar c = Calendar.getInstance();
	private BookFromLibrary bookFromLibrary = null;

	// storing the id of the book that should be edited
	private int editableBookID = 0;

	// //////////////// on create stuff
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.add_book);

		// // get bundle
		Bundle bundle = getIntent().getExtras();
		// / if null, we are just creating a new book!
		if (bundle == null) {
			Log.d(TAG, "Bundle for this activity is null: creating hash map..");
			isEdit = false;
			map = new HashMap<String, Object>();
			dialogCreator = new DialogCreator(map);
		}
		// //// else, we are editing!!
		else {
			map = new HashMap<String, Object>();
			Log.d(TAG, "GIVEN BUNDLE!!");
			editableBookID = bundle.getInt("bookID");

			String bookName = bundle.getString("bookName");
			String bookAuthor = bundle.getString("bookAuthor");
			String bookISBN = bundle.getString("bookISBN");
			String bookPublisher = bundle.getString("bookPublisher");
			String bookLanguage = bundle.getString("bookLanguage");
			int bookYear = bundle.getInt("bookYear");
			book = new Book(bookYear, bookName, bookAuthor, bookPublisher,
					bookLanguage, bookISBN);
			book.setBookID(editableBookID);
			map.put(getString(R.string.book_name_text), bookName);
			map.put(getString(R.string.book_author_text), bookAuthor);
			map.put(getString(R.string.book_isbn_text), bookISBN);
			map.put(getString(R.string.book_language_text), bookLanguage);
			map.put(getString(R.string.book_publisher_text), bookPublisher);
			map.put(getString(R.string.book_year_text), bookYear + "");
			Log.d(TAG, "MAP CRETED: " + map.size());
			dialogCreator = new DialogCreator(map);
			isEdit = true;
		}

		txtBookName = (TextView) findViewById(R.id.bookName);
		txtBookName.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				showDialog(DIALOG_ENTER_NAME);
				Log.d(TAG, "Enter Name dialog clicked");
			}
		});
		// /// check if we are editing a book or creating it from scratch
		if (map.containsKey(getString(R.string.book_name_text)))
			txtBookName.setText(map.get(getString(R.string.book_name_text))
					.toString());

		txtBookAuthor = (TextView) findViewById(R.id.bookAuthor);
		txtBookAuthor.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				showDialog(DIALOG_ENTER_AUTHOR);
				Log.d(TAG, "Enter Author dialog clicked");
			}
		});
		// /// check if we are editing a book or creating it from scratch
		if (map.containsKey(getString(R.string.book_author_text)))
			txtBookAuthor.setText(map.get(getString(R.string.book_author_text))
					.toString());

		for (int i = 0; i < additionalListTextViews.length; i++) {
			additionalListTextViews[i] = null;
		}

		expListAdditionalOptions = (ExpandableListView) findViewById(R.id.bookAdditionalOptions);
		expListAdapter = new AdditionalOptionsExpandableListAdapter();
		expListAdditionalOptions.setAdapter(expListAdapter);

		buttonAddBook = (ImageButton) findViewById(R.id.buttonAddBook);
		buttonAddBook.setOnClickListener(this);

		buttonAddLibraryForThisBook = (ImageButton) findViewById(R.id.buttonAddLibrary);
		buttonAddLibraryForThisBook.setOnClickListener(addLibraryClicked);
	}

	// ////////////// ------- BEGIN dialog stuff ------------//////////////
	@Override
	protected Dialog onCreateDialog(int id) {
		Log.d(TAG, "MAP SIZE: " + map.size());
		if (dialogCreator == null)
			dialogCreator = new DialogCreator(map, TAG, expListAdapter);
		else if (dialogCreator.getExpListAdapter() == null)
			dialogCreator = new DialogCreator(map, TAG, expListAdapter);

		switch (id) {
		case DIALOG_ENTER_NAME:
			return dialogCreator.createDialog(this,
					getString(R.string.book_name_text) + "!",
					getString(R.string.book_name_text), txtBookName, false);
		case DIALOG_ENTER_AUTHOR:
			return dialogCreator.createDialog(this,
					getString(R.string.book_author_text) + "!",
					getString(R.string.book_author_text), txtBookAuthor, false);
		case DIALOG_ENTER_PUBLISHER:
			return dialogCreator.createDialog(this,
					getString(R.string.book_publisher_text) + "!",
					getString(R.string.book_publisher_text),
					additionalListTextViews[0], false);
		case DIALOG_ENTER_LANGUAGE:
			return dialogCreator.createDialog(this,
					getString(R.string.book_language_text) + "!",
					getString(R.string.book_language_text),
					additionalListTextViews[1], false);
		case DIALOG_ENTER_ISBN:
			return dialogCreator.createDialog(this,
					getString(R.string.book_isbn_text) + "!",
					getString(R.string.book_isbn_text),
					additionalListTextViews[2], false);
		case DIALOG_ENTER_YEAR:
			return dialogCreator.createDialog(this,
					getString(R.string.book_year_text) + "!",
					getString(R.string.book_year_text),
					additionalListTextViews[3], true);
		case DIALOG_SHOW_SPINNER:
			AlertDialog.Builder builder = new Builder(AddBookActivity.this);
			builder.setTitle(getString(R.string.library_add));
			builder.setAdapter(libraryAdapter,
					new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							selectedLibrary = libraryAdapter.getItem(which);
							dialog.dismiss();
							showLongToast(getString(R.string.toastMessage_inform_librarySelected)
									+ selectedLibrary.toString());
						}
					});
			builder.show();
		}
		return null;
	}

	// /// ---- END DIALOG STUFF ----- // ////

	// // ----- BEGIN EXPANDABLE LIST STUFF ----/////////
	private class AdditionalOptionsExpandableListAdapter extends
			BaseExpandableListAdapter {
		private String[] parents = { "	Additional Options" };
		private String[][] children = { {
				getString(R.string.book_publisher_text),
				getString(R.string.book_language_text),
				getString(R.string.book_isbn_text),
				getString(R.string.book_year_text) } };

		private int[][] dialogNumbers = { { DIALOG_ENTER_PUBLISHER,
				DIALOG_ENTER_LANGUAGE, DIALOG_ENTER_ISBN, DIALOG_ENTER_YEAR } };

		public AdditionalOptionsExpandableListAdapter() {
			if (dialogCreator == null)
				dialogCreator = new DialogCreator(map, TAG, expListAdapter);
		}

		@Override
		public Object getChild(int groupPosition, int childPosition) {
			return children[groupPosition][childPosition];
		}

		@Override
		public long getChildId(int groupPosition, int childPosition) {
			return childPosition;
		}

		@Override
		public View getChildView(final int groupPosition,
				final int childPosition, boolean isLastChild, View convertView,
				ViewGroup parent) {
			TextView textView = getGenericView();
			// check if key already exists in map; if not, then set the default
			// text
			if (!dialogCreator.getMap().containsKey(
					(children[groupPosition][childPosition]))) {
				textView.setText(getChild(groupPosition, childPosition)
						.toString());
			}

			// else if it exists:
			else {
				String s = (String) dialogCreator.getMap().get(
						children[groupPosition][childPosition]);
				// check whether it is null, 0 etc; if it is, set default value!
				if (s.equals("") || s.equals("0") || s.equals("null")) {
					textView.setText(getChild(groupPosition, childPosition)
							.toString());
				}
				// else set value from map as text for TextView
				else
					textView.setText(s);
			}
			textView.setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View v) {
					showDialog(dialogNumbers[groupPosition][childPosition]);
					Log.d(TAG, "CLICKED: "
							+ dialogNumbers[groupPosition][childPosition]);
				}
			});
			Log.d(TAG, "CHILD NUMBER IS: " + childPosition);
			additionalListTextViews[childPosition] = textView;
			return additionalListTextViews[childPosition];
		}

		@Override
		public int getChildrenCount(int groupPosition) {
			return children[groupPosition].length;
		}

		@Override
		public Object getGroup(int groupPosition) {
			return parents[groupPosition];
		}

		@Override
		public int getGroupCount() {
			return parents.length;
		}

		@Override
		public long getGroupId(int groupPosition) {
			return groupPosition;
		}

		@Override
		public View getGroupView(int groupPosition, boolean isExpanded,
				View convertView, ViewGroup parent) {
			TextView textView = getGenericView();
			textView.setText(getGroup(groupPosition).toString());
			return textView;
		}

		@Override
		public boolean hasStableIds() {
			return true;
		}

		@Override
		public boolean isChildSelectable(int groupPosition, int childPosition) {
			return true;
		}

		public TextView getGenericView() {
			// Layout parameters for the ExpandableListView
			AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
					ViewGroup.LayoutParams.MATCH_PARENT, 64);

			TextView textView = new TextView(AddBookActivity.this);
			textView.setLayoutParams(lp);
			// Center the text vertically
			textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
			// Set the text starting position
			textView.setPadding(36, 0, 0, 0);
			// textView.setGravity(Gravity.CENTER);
			// textView.setBackgroundDrawable(getResources().getDrawable(R.drawable.back));
			return textView;
		}

		@Override
		public void notifyDataSetChanged() {
			// TODO Auto-generated method stub
			super.notifyDataSetChanged();
		}
	}

	// //----- END EXPANDABLE LIST STUFF ----/////////

	// ////////////// add book button onClick stuff
	@Override
	public void onClick(View v) {
		String bookName = null, bookAuthor = null, bookPublisher = null, bookLanguage = null, bookISBN = null;
		int bookYear = 0;
		map = dialogCreator.getMap();

		if (map.isEmpty()) {
			showLongToast(getString(R.string.toastMessage_error_noInput));
		} else {
			// /// check for library's name
			if (map.containsKey(getString(R.string.book_name_text))) {
				bookName = (String) map.get(getString(R.string.book_name_text));
			} else {
				showLongToast(getString(R.string.toastMessage_error_general)
						+ getString(R.string.book_name_text));
				return;
			}

			// // check for library's borrow max
			if (map.containsKey(getString(R.string.book_author_text))) {
				bookAuthor = (String) map
						.get(getString(R.string.book_author_text));
			} else {
				showLongToast(getString(R.string.toastMessage_error_general)
						+ getString(R.string.book_author_text));
				return;
			}

			// // check for library's maxNumExt
			if (map.containsKey(getString(R.string.book_publisher_text))) {
				bookPublisher = (String) map
						.get(getString(R.string.book_publisher_text));
			}

			// // check for library's address
			if (map.containsKey(getString(R.string.book_language_text))) {
				bookLanguage = (String) map
						.get(getString(R.string.book_language_text));
			}

			// // check for library's email
			if (map.containsKey(getString(R.string.book_isbn_text))) {
				bookISBN = (String) map.get(getString(R.string.book_isbn_text));
			}

			// // check for library's phone
			if (map.containsKey(getString(R.string.book_year_text))) {
				bookYear = Integer.parseInt((String) map
						.get(getString(R.string.book_year_text)));
			}

			// // create new library object
			book = new Book(bookYear, bookName, bookAuthor, bookPublisher,
					bookLanguage, bookISBN);

			// check if book is unique, if not, do nothing
			AsyncTask<Object, Object, Object> returnBook = new ReturnBooks(
					AddBookActivity.this).execute(book);
			try {
				Cursor cursor = (Cursor) returnBook.get();
				if (cursor.moveToNext()) {
					showLongToast(getString(R.string.toastMessage_error_alreadyExists));
					return;
				}
				// ELSE: UNIQUE BOOK

				// // ----- If we are adding a new book
				if (!isEdit) {
					new AddBook(AddBookActivity.this).execute(book);
					Log.d(TAG,
							"SUCCESSFULLY ADDED A NEW BOOK: " + book.toString());
				}
				// / ----- Else, if we are editing the existing one
				else {
					book.setBookID(editableBookID);
					new UpdateBook(AddBookActivity.this).execute(book);
					Log.d(TAG, "SUCCESSFULLY UPDATED BOOK " + book.toString());
				}

				// /// code for registring this book with a library (i.e.
				// bookFromLibrary..)
				if (!(selectedLibrary == null)) {
					returnBook = new ReturnBooks(AddBookActivity.this)
							.execute(book);

					cursor = (Cursor) returnBook.get();
					cursor.moveToNext();
					Log.d(TAG, "Cursor moved to next");

					book.setBookID(cursor.getInt(0));
					Log.d(TAG, "BookID set: " + book.getBookID());
					Date date = new Date(Calendar.getInstance().getTime()
							.getTime());
					Log.d(TAG, "DATE: " + date.toGMTString());
					Log.d(TAG, "DATE IN MILLISECONDS: " + date.getTime());

					bookFromLibrary = new BookFromLibrary(book.getBookID(),
							selectedLibrary.getLibraryID(), date.getTime());
					Log.d(TAG,
							"CREATED BOOK FROM LIBRARY: "
									+ bookFromLibrary.toString());

					// *** only add new book from library if this library wasnt
					// selected before!
					if (isEdit) {
						AsyncTask<Object, Object, Object> returnBooksFromLib = new ReturnBooksFromLibrary(
								AddBookActivity.this).execute(bookFromLibrary);
						cursor = (Cursor) returnBooksFromLib.get();
						if (cursor.moveToNext()) {
							// showLongToast(getString(R.string.toastMessage_error_alreadyExists));
							Log.d(TAG,
									"THIS BOOK IS ALREADY REGISTRED WITH THUS LIBRARY< THUS THERE IS NO NEED TO CREATE ANOTHER BookFromLibrary value in DB!!");
							return;
						}
					}

					new AddBookFromLibrary(AddBookActivity.this)
							.execute(bookFromLibrary);
					Log.d(TAG,
							"Registed book for library: "
									+ bookFromLibrary.toString());
					showLongToast(getString(R.string.toastMessage_success_addBookForLibrary));
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ExecutionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

	}

	// // REGISTER LIBRARY FOR THIS BOOK
	private OnClickListener addLibraryClicked = new OnClickListener() {
		@Override
		public void onClick(View v) {
			library = new Library();
			Log.d(TAG, "variable library Created as new()");

			// View view = findViewById(R.layout.library_row);
			libraryAdapter = new ArrayAdapter<Library>(AddBookActivity.this,
					R.layout.library_row, R.id.libraryName);
			Log.d(TAG, "variable libraryAdapter Created as new()");
			libraryAdapter.setDropDownViewResource(R.layout.library_row);
			Log.d(TAG, "libraryAdapter - setDropDownViewResource");

			AsyncTask<Object, Object, Object> returnAllLibraries = new ReturnAllLibraries(
					AddBookActivity.this).execute(library);
			Cursor cursor = null;
			try {
				cursor = (Cursor) returnAllLibraries.get();
			} catch (InterruptedException e) {
				e.printStackTrace();
				showLongToast(e.getMessage());
			} catch (ExecutionException e) {
				e.printStackTrace();
				showLongToast(e.getMessage());
			}

			// if empty, simply inform the user
			if (!cursor.moveToFirst())
				showLongToast(getString(R.string.toastMessage_error_noLibrariesInDB));
			// ELSE
			else {
				library = new Library(cursor.getInt(0), cursor.getInt(1),
						cursor.getInt(2), cursor.getString(3),
						cursor.getString(4), cursor.getString(5),
						cursor.getString(6));
				libraryAdapter.add(library);
				Log.d(TAG, "new library: " + library.toString());
				// get all libraries
				while (cursor.moveToNext()) {
					library = new Library(cursor.getInt(0), cursor.getInt(1),
							cursor.getInt(2), cursor.getString(3),
							cursor.getString(4), cursor.getString(5),
							cursor.getString(6));
					libraryAdapter.add(library);
					Log.d(TAG, "new library: " + library.toString());
				}
				Log.d(TAG,
						"Finished fetching libraries: adapter completed with data");

				// show the spinner inside dialog
				showDialog(DIALOG_SHOW_SPINNER);
			}

		}
	};

	private void showLongToast(String text) {
		Toast.makeText(AddBookActivity.this, text, Toast.LENGTH_LONG).show();
	}
}
